﻿using CommonTools;
using Discord.Net.WebSockets;
using Discord.WebSocket;
using System.Net.WebSockets;
using System.Threading.Tasks;
using CommonTools.Extension;
using CommonTools.Util;
using Discord.Rest;
using ViewModel.Enum;
using YukariToolBox.LightLog;

namespace Discord.Bot;

/// <summary>
/// 机器人客户端
/// </summary>
public class DiscordBotClient
{
    #region 属性

    /// <summary>
    /// DiscordSocketClient
    /// </summary>
    private DiscordSocketClient? _client { get; set; }

    /// <summary>
    /// DiscordSocketConfig
    /// </summary>
    private DiscordSocketConfig Config { get; set; }

    /// <summary>
    /// 机器人token
    /// </summary>
    private string Bot_Token { get; set; }

    #endregion

    #region 私有字段

    /// <summary>
    /// 客户端已准备启动标识
    /// </summary>
    internal readonly bool _isReady;

    /// <summary>
    /// 客户端已启动
    /// </summary>
    internal bool _isRunning;

    /// <summary>
    /// dispose flag
    /// </summary>
    internal bool _disposed;

    #endregion

    #region 构造函数

    public DiscordBotClient(string token)
    {

        Log.Info("SuiFeng", "Ciallo～");
        Log.Debug("SuiFeng", "Developer QQ Group：872905123");
        Log.Verbose("System", Environment.OSVersion.ToString());
        Log.Verbose("Runtime", Environment.Version.ToString());


        _isReady = false;
        Log.Info("Discord", "Discord Socket客户端初始化");
        Bot_Token = token;
        Config = new DiscordSocketConfig
        {
            GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
        };

        //全局异常事件
        AppDomain.CurrentDomain.UnhandledException += (_, args) =>
        {
            DiscordUtil.FriendlyException(args);
        };
        _isReady = true;
    }

    #endregion

    #region 客户端启停

    /// <summary>
    /// <para>启动 Discord 服务</para>
    /// <para>启动客户端并自动连接服务器</para>
    /// </summary>
    public async ValueTask StartService()
    {
        if (!_isReady)
        {
            Log.Warning("Discord", "服务已经启动了！");
            return;
        }

        _client = new DiscordSocketClient(Config);

        _client.Log += (log) =>
        {
            Log.Debug("Discord Log", $"{log.ToString()}");
            return Task.CompletedTask;
        };

        //链接成功事件
        _client.Ready += () =>
        {
            Log.Info("Discord", "Discord WebSocket客户端正在运行已连接至Discord服务器");
            Log.Info("Discord", $"Logged in as {_client.CurrentUser} (ID: {_client.CurrentUser.Id})");
            return Task.CompletedTask;
        };

        //消息接收事件
        _client.MessageReceived += async (message) =>
        {
            if (message.Author.Id == _client.CurrentUser.Id)
                return;

            Log.Debug("Discord", $"on_message: {message.Content}");
            Log.Debug("Discord", $"on_message embeds: {message.Embeds.ToList()}");
            string content = message.Content;
            string triggerId = BotUtil.MatchTriggerId(content);
            if (string.IsNullOrEmpty(triggerId))
            {
                return;
            }

            string triggerStatus;
            if (content.IndexOf("Waiting to start", StringComparison.Ordinal) != -1)
            {
                triggerStatus = TriggerStatus.Start.GetEnumText();
                BotUtil.SetTemp(triggerId);
            }
            else if (content.IndexOf("(Stopped)", StringComparison.Ordinal) != -1)
            {
                triggerStatus = TriggerStatus.Error.GetEnumText();
                BotUtil.PopTemp(triggerId);
            }
            else
            {
                triggerStatus = TriggerStatus.End.GetEnumText();
                BotUtil.PopTemp(triggerId);
            }

            await BotUtil.CallBackTrigger(triggerId, triggerStatus, message);

        };

        //消息修改事件
        _client.MessageUpdated += async (before, after, channel) =>
        {

            if (after.Author.Id == _client.CurrentUser.Id)
                return;
            Log.Debug("Discord", $"on_message_edit: {after.Content}");

            if (after.Embeds.Any())
            {
                var embed = after.Embeds.FirstOrDefault();
                if (embed == null)
                {
                    return;
                }

                if (!embed.Image.HasValue)
                {
                    return;
                }

                string json = embed.ToJsonString();
                Log.Debug("Discord", $"on_message_edit embeds: {json}");
                string triggerStatus = TriggerStatus.Text.GetEnumText();
                (bool isTrue, string DTriggerId) = await BotUtil.CallBackDescribe(triggerStatus, after);
                if (!isTrue)
                {
                    return;
                }
                BotUtil.PopTemp(DTriggerId);
                return;
            }

            string triggerId = BotUtil.MatchTriggerId(after.Content);
            if (string.IsNullOrEmpty(triggerId))
            {
                return;
            }

            await BotUtil.CallBackTrigger(triggerId, TriggerStatus.Generating.GetEnumText(), after);
        };

        //消息删除事件
        _client.MessageDeleted += async (before, after) =>
        {
            var message = await before.GetOrDownloadAsync();
            if (message == null)
            {
                return;
            }

            if (message.Author.Id == _client.CurrentUser.Id)
                return;

            string triggerId = BotUtil.MatchTriggerId(message.Content);
            if (string.IsNullOrEmpty(triggerId))
            {
                return;
            }

            if (!BotUtil.IsExitTemp(triggerId))
            {
                return;
            }
            Log.Debug("Discord", $"on_message_delete: {(before.HasValue ? before.Value.Content : "")}");
            Log.Warning("Discord", $"sensitive content: {before.Value.Content}");

            string triggerStatus = TriggerStatus.Banned.GetEnumText();
            BotUtil.PopTemp(triggerId);
            await BotUtil.CallBackTrigger(triggerId, triggerStatus, message);
        };

        //登录
        await _client.LoginAsync(TokenType.Bot, Bot_Token);
        //开始客户端
        await _client.StartAsync();

        Log.Info("Discord", "Discord WebSocket客户端正在运行等待连接至Discord服务器");
        _isRunning = true;
    }

    /// <summary>
    /// <para>停止 Discord 服务</para>
    /// <para>停止Discord客户端</para>
    /// </summary>
    public async ValueTask StopService()
    {
        if (_disposed)
            return;
        Log.Warning("Discord", $"DiscordWebsocket客户端正在停止...");

        //停止客户端
        await _client?.StopAsync()!;
        await _client.DisposeAsync();
        _isRunning = false;
        Log.Warning("Discord", $"DiscordWebsocket客户端正在停止客户端已停止");
    }

    /// <summary>
    /// GC析构函数
    /// </summary>
    ~DiscordBotClient()
    {
        Log.Warning("Destructor Call", $"");
        Dispose();
    }

    /// <summary>
    /// 释放资源并断开链接
    /// </summary>
    public void Dispose()
    {
        StopService().AsTask().Wait();
        _client?.Dispose();
        _disposed = true;
        Task.Delay(100).Wait();
        GC.SuppressFinalize(this);
    }


    #endregion
}